﻿package cz.dadul.adventure.model 
{
	import cz.dadul.adventure.model.Element;
	import cz.dadul.adventure.model.events.*;
	import flash.display.*;
	import flash.events.MouseEvent;
	
	/**
	 * ...
	 * @author Dadul
	 */
	public class ClickableItem extends Item implements IClickable
	{
		// Basic events
		public static const EVENT_OVER:String = "event.item.over";
		public static const EVENT_OUT:String = "event.item.out";
		public static const EVENT_CLICK:String = "event.item.click";
		public static const EVENT_READY:String = "event.item.ready";
		public static const EVENT_INTERACT:String = "event.item.interact";
		
		public static const FRAME_PREFIX_READY:String = "r";
		public static const FRAME_PREFIX_INTERACT:String = "i";
				
		protected var _clickableLogic:Array;
		protected var _hitMovieClip:MovieClip;
		private var _hitMcName:String;
		
		public function ClickableItem(name:String, mc:MovieClip, hitMcName:String = null)
		{
			super(name, mc);
			this._clickableLogic = new Array();
			this._hitMcName = hitMcName;
		}		
		
		protected override function init():void {
			addTimelineBehaviour();			
			
			super.init();
			// Determine clickable hit movieclip
			if (this._hitMcName == null) {
				this._hitMovieClip = this._content;
			} else {
				this._hitMovieClip = this._content.getChildByName(this._hitMcName) as MovieClip;
			}		
			// Set hit movie clip attributes
			this._hitMovieClip.useHandCursor = true;
			this._hitMovieClip.mouseChildren = false;
			// Set clickable events
			setEvents();
		}
		
		protected function setEvents():void {
			this._hitMovieClip.addEventListener(MouseEvent.CLICK, onClick);			
			this._hitMovieClip.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
			this._hitMovieClip.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
		}
		
	
		protected function onClick(e:MouseEvent):void {			
			// Dispatch event
			dispatchEvent(new DataHolderEvent(EVENT_CLICK, this));	
			
			// Perform clickable logic action (if found)
			if (this._clickableLogic[this._state] != null) {
				// try determined by the state
				performAction(this._clickableLogic[this._state]);
			} else if(this._clickableLogic[ElementActionSet.DEFAULT] != null) {
				// try default logic
				performAction(this._clickableLogic[ElementActionSet.DEFAULT]);
			}

		}
		
		protected function onMouseOver(e:MouseEvent):void {
			dispatchEvent(new DataHolderEvent(EVENT_OVER, this));
		}
		
		protected function onMouseOut(e:MouseEvent):void {
			dispatchEvent(new DataHolderEvent(EVENT_OUT, this));
		}
		
		protected function addTimelineBehaviour():void {			
			// ready timeline action
			var action:Function = function(self: Element, frameName: String):Function {				
				return function():void {	
					self.stop();
					// Dispatch EVENT_TIMELINE 
					self.dispatchEvent(new TimelineEvent(Element.EVENT_TIMELINE, this.name, frameName));
					// User-defined action
					ClickableItem(self).ready();
				}
			}				
			// interact timeline action
			action = function(self: Element, frameName: String):Function {				
				return function():void {	
					self.stop();
					// Dispatch EVENT_TIMELINE 
					self.dispatchEvent(new TimelineEvent(Element.EVENT_TIMELINE, this.name, frameName));
					// User-defined action
					ClickableItem(self).interact();
				}
			}				
			
			addPrefixBehaviour(FRAME_PREFIX_INTERACT, action);
		}		 
		
		/*
		 * Public functions
		 */
		/**
		 * Used, when all actions are finished and the item is ready 
		 * for next player's input (In the controllers, it determines
		 * e.g. Mouse pointer).
		 */
		public function ready():void {
			dispatchEvent(new DataHolderEvent(EVENT_READY, this));	
		}
		 
		
		/**
		 * 
		 * Used, when the user click on the item and the item 
		 * somehow interacts with the user -> it needs special 
		 * animation etc.
		 */
		public function interact():void {
			dispatchEvent(new DataHolderEvent(EVENT_INTERACT, this));
		}
		
		/**
		*  TODO: prepsat na mouseEnabled!		
		*/	
		public function enableFocus(enable: Boolean = true):void {
			this._hitMovieClip.mouseEnabled = enable;			
		}
		
		/*
		 * SETTERS / GETTERS
		 */ 
		public function set clickableLogic(l:Array):void {
			this._clickableLogic = l;
		}
		public function get clickableLogic():Array {
			return this._clickableLogic;
		}
		
	}

}